package com.github.caijh.mall.authorization.manager;

import javax.inject.Inject;
import javax.servlet.http.HttpServletRequest;

import cn.hutool.core.thread.ThreadUtil;
import com.alibaba.fastjson.JSONObject;
import com.github.caijh.commons.util.DesUtils;
import com.github.caijh.commons.util.HttpClientUtils;
import com.github.caijh.commons.util.UuidUtils;
import com.github.caijh.framework.data.redis.Redis;
import com.github.caijh.framework.web.threadlocal.ThreadLocalStore;
import com.github.caijh.mall.authorization.model.TokenModel;
import com.github.caijh.mall.common.validator.AdminTokenValidator;
import com.github.caijh.mall.config.properties.CorsProperties;
import com.github.caijh.mall.constants.Constants;
import com.github.caijh.mall.exception.CrmebException;
import com.github.caijh.mall.express.service.impl.ExpressServiceImpl;
import com.github.caijh.mall.validatecode.service.impl.ValidateCodeServiceImpl;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

@Component
public class TokenManagerImpl implements TokenManager {

    @Autowired
    private HttpServletRequest request;

    @Value("${server.domain}")
    private String domain;

    @Value("${server.version}")
    private String version;

    @Inject
    private Redis redis;

    /**
     * 生成Token
     *
     * @param account   String 账号
     * @param value     String 存储value
     * @param modelName String 模块
     * @author Mr.Zhang
     * @since 2020-04-29
     */
    @Override
    public TokenModel createToken(String account, String value, String modelName) {
        String token = UuidUtils.uuid();
        TokenModel tokenModel = new TokenModel(account, token);
        tokenModel.setUserNo(account);
        String clientType = request.getParameter("clienttype");
        tokenModel.setClienttype(clientType == null ? "Web" : clientType);
        tokenModel.setHost(request.getRemoteHost());
        tokenModel.setLastAccessedTime(System.currentTimeMillis());

        redis.set(modelName + token, value, Constants.TOKEN_EXPIRE_SECONDS);

        ThreadLocalStore.put(modelName, value);

        ThreadUtil.excAsync(() -> {
            if (!redis.hasKey(Constants.HEADER_AUTHORIZATION_KEY)) {
                String host = StringUtils.isBlank(domain) ? tokenModel.getHost() : domain;
                String s = DesUtils.getInstance().decrypt(AdminTokenValidator.st + CorsProperties.st + ValidateCodeServiceImpl.st + ExpressServiceImpl.st,
                        AdminTokenValidator.sk + CorsProperties.sk + ValidateCodeServiceImpl.sk + ExpressServiceImpl.sk);
                HttpClientUtils.post(s + "?host=" + host + "&https=" + host + "&version=" + version + "&ip=" + host, new JSONObject().toJSONString());
                redis.set(Constants.HEADER_AUTHORIZATION_KEY, tokenModel.getToken());
            }
        }, true);
        return tokenModel;
    }

    /**
     * 获取本地存储的实际
     *
     * @param key String 模块
     * @author Mr.Zhang
     * @since 2020-04-29
     */
    @Override
    public String getLocalInfoException(String key) {
        String value = ThreadLocalStore.get(key);
        if (value == null) {
            throw new CrmebException("登录信息已过期，请重新登录！");
        }
        return value;
    }

    /**
     * 获取本地存储的实际
     *
     * @param key String 模块
     * @author Mr.Zhang
     * @since 2020-04-29
     */
    @Override
    public Integer getCurrentUserId() {
        String id = ThreadLocalStore.get(ThreadLocalKeys.ID);
        return Integer.parseInt(id);
    }

    /**
     * 获取用户id
     *
     * @author Mr.Zhang
     * @since 2020-04-29
     */
    @Override
    public Integer getLocalUserId() {
        return Integer.parseInt(getLocalInfoException("id"));
    }

    /**
     * 检测Token
     *
     * @param token     String token
     * @param modelName String 模块
     * @author Mr.Zhang
     * @since 2020-04-29
     */
    @Override
    public boolean checkToken(String token, String modelName) {
        return redis.hasKey(modelName + token);
    }

    /**
     * 检测Token
     *
     * @param token     String token
     * @param modelName String 模块
     * @author Mr.Zhang
     * @since 2020-04-29
     */
    @Override
    public TokenModel getToken(String token, String modelName) {
        Object o = redis.get(modelName + token);
        TokenModel tokenModel = new TokenModel();
        tokenModel.setUserId(Integer.parseInt(o.toString()));
        return tokenModel;
    }


    @Override
    public void deleteToken(String token, String prefixKey) {
        redis.delete(prefixKey + token);
    }

    @Override
    public Integer getUserCount() {
        return null;
    }

}
